home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / a_utils / perl / perl5a1.lha / perl5alpha1 / do / splice < prev    next >
Encoding:
Text File  |  1992-08-15  |  4.6 KB  |  193 lines

  1. int
  2. do_splice(ary,gimme,arglast)
  3. register ARRAY *ary;
  4. int gimme;
  5. int *arglast;
  6. {
  7.     register STR **st = stack->ary_array;
  8.     register int sp = arglast[1];
  9.     int max = arglast[2] + 1;
  10.     register STR **src;
  11.     register STR **dst;
  12.     register int i;
  13.     register int offset;
  14.     register int length;
  15.     int newlen;
  16.     int after;
  17.     int diff;
  18.     STR **tmparyval;
  19.  
  20.     if (++sp < max) {
  21.     offset = (int)str_gnum(st[sp]);
  22.     if (offset < 0)
  23.         offset += ary->ary_fill + 1;
  24.     else
  25.         offset -= arybase;
  26.     if (++sp < max) {
  27.         length = (int)str_gnum(st[sp++]);
  28.         if (length < 0)
  29.         length = 0;
  30.     }
  31.     else
  32.         length = ary->ary_max + 1;        /* close enough to infinity */
  33.     }
  34.     else {
  35.     offset = 0;
  36.     length = ary->ary_max + 1;
  37.     }
  38.     if (offset < 0) {
  39.     length += offset;
  40.     offset = 0;
  41.     if (length < 0)
  42.         length = 0;
  43.     }
  44.     if (offset > ary->ary_fill + 1)
  45.     offset = ary->ary_fill + 1;
  46.     after = ary->ary_fill + 1 - (offset + length);
  47.     if (after < 0) {                /* not that much array */
  48.     length += after;            /* offset+length now in array */
  49.     after = 0;
  50.     if (!ary->ary_alloc) {
  51.         afill(ary,0);
  52.         afill(ary,-1);
  53.     }
  54.     }
  55.  
  56.     /* At this point, sp .. max-1 is our new LIST */
  57.  
  58.     newlen = max - sp;
  59.     diff = newlen - length;
  60.  
  61.     if (diff < 0) {                /* shrinking the area */
  62.     if (newlen) {
  63.         New(451, tmparyval, newlen, STR*);    /* so remember insertion */
  64.         Copy(st+sp, tmparyval, newlen, STR*);
  65.     }
  66.  
  67.     sp = arglast[0] + 1;
  68.     if (gimme == G_ARRAY) {            /* copy return vals to stack */
  69.         if (sp + length >= stack->ary_max) {
  70.         astore(stack,sp + length, Nullstr);
  71.         st = stack->ary_array;
  72.         }
  73.         Copy(ary->ary_array+offset, st+sp, length, STR*);
  74.         if (ary->ary_flags & ARF_REAL) {
  75.         for (i = length, dst = st+sp; i; i--)
  76.             str_2mortal(*dst++);    /* free them eventualy */
  77.         }
  78.         sp += length - 1;
  79.     }
  80.     else {
  81.         st[sp] = ary->ary_array[offset+length-1];
  82.         if (ary->ary_flags & ARF_REAL) {
  83.         str_2mortal(st[sp]);
  84.         for (i = length - 1, dst = &ary->ary_array[offset]; i > 0; i--)
  85.             str_free(*dst++);    /* free them now */
  86.         }
  87.     }
  88.     ary->ary_fill += diff;
  89.  
  90.     /* pull up or down? */
  91.  
  92.     if (offset < after) {            /* easier to pull up */
  93.         if (offset) {            /* esp. if nothing to pull */
  94.         src = &ary->ary_array[offset-1];
  95.         dst = src - diff;        /* diff is negative */
  96.         for (i = offset; i > 0; i--)    /* can't trust Copy */
  97.             *dst-- = *src--;
  98.         }
  99.         Zero(ary->ary_array, -diff, STR*);
  100.         ary->ary_array -= diff;        /* diff is negative */
  101.         ary->ary_max += diff;
  102.     }
  103.     else {
  104.         if (after) {            /* anything to pull down? */
  105.         src = ary->ary_array + offset + length;
  106.         dst = src + diff;        /* diff is negative */
  107.         Move(src, dst, after, STR*);
  108.         }
  109.         Zero(&ary->ary_array[ary->ary_fill+1], -diff, STR*);
  110.                         /* avoid later double free */
  111.     }
  112.     if (newlen) {
  113.         for (src = tmparyval, dst = ary->ary_array + offset;
  114.           newlen; newlen--) {
  115.         *dst = Str_new(46,0);
  116.         str_sset(*dst++,*src++);
  117.         }
  118.         Safefree(tmparyval);
  119.     }
  120.     }
  121.     else {                    /* no, expanding (or same) */
  122.     if (length) {
  123.         New(452, tmparyval, length, STR*);    /* so remember deletion */
  124.         Copy(ary->ary_array+offset, tmparyval, length, STR*);
  125.     }
  126.  
  127.     if (diff > 0) {                /* expanding */
  128.  
  129.         /* push up or down? */
  130.  
  131.         if (offset < after && diff <= ary->ary_array - ary->ary_alloc) {
  132.         if (offset) {
  133.             src = ary->ary_array;
  134.             dst = src - diff;
  135.             Move(src, dst, offset, STR*);
  136.         }
  137.         ary->ary_array -= diff;        /* diff is positive */
  138.         ary->ary_max += diff;
  139.         ary->ary_fill += diff;
  140.         }
  141.         else {
  142.         if (ary->ary_fill + diff >= ary->ary_max)    /* oh, well */
  143.             astore(ary, ary->ary_fill + diff, Nullstr);
  144.         else
  145.             ary->ary_fill += diff;
  146.         dst = ary->ary_array + ary->ary_fill;
  147.         for (i = diff; i > 0; i--) {
  148.             if (*dst)            /* TARG was hanging around */
  149.             str_free(*dst);        /*  after $#foo */
  150.             dst--;
  151.         }
  152.         if (after) {
  153.             dst = ary->ary_array + ary->ary_fill;
  154.             src = dst - diff;
  155.             for (i = after; i; i--) {
  156.             *dst-- = *src--;
  157.             }
  158.         }
  159.         }
  160.     }
  161.  
  162.     for (src = st+sp, dst = ary->ary_array + offset; newlen; newlen--) {
  163.         *dst = Str_new(46,0);
  164.         str_sset(*dst++,*src++);
  165.     }
  166.     sp = arglast[0] + 1;
  167.     if (gimme == G_ARRAY) {            /* copy return vals to stack */
  168.         if (length) {
  169.         Copy(tmparyval, st+sp, length, STR*);
  170.         if (ary->ary_flags & ARF_REAL) {
  171.             for (i = length, dst = st+sp; i; i--)
  172.             str_2mortal(*dst++);    /* free them eventualy */
  173.         }
  174.         Safefree(tmparyval);
  175.         }
  176.         sp += length - 1;
  177.     }
  178.     else if (length--) {
  179.         st[sp] = tmparyval[length];
  180.         if (ary->ary_flags & ARF_REAL) {
  181.         str_2mortal(st[sp]);
  182.         while (length-- > 0)
  183.             str_free(tmparyval[length]);
  184.         }
  185.         Safefree(tmparyval);
  186.     }
  187.     else
  188.         st[sp] = &str_undef;
  189.     }
  190.     return sp;
  191. }
  192.  
  193.